<script setup lang="ts">
import { Close, Download, Loading, Warning } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { init } from 'pptx-preview';
import { nextTick, ref, watch } from 'vue';

interface Props {
  modelValue?: boolean;
  pptUrl?: string;
  downloadUrl?: string;
}

interface Emits {
  (e: 'update:modelValue', value: boolean): void;
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: false,
  pptUrl: '',
  downloadUrl: '',
});

const emit = defineEmits<Emits>();

const visible = ref(false);
const loading = ref(false);
const error = ref('');
const pptPreviewRef = ref<HTMLElement>();

// PPT预览器尺寸配置 - 调整为更大尺寸以充分利用空间
const width = 900;
const height = 540;

// PPT预览器实例
let pptxPreviewer: any = null;

watch(() => props.modelValue, async (val: boolean) => {
  visible.value = val;
  if (val && props.pptUrl) {
    // 延迟初始化，确保对话框完全打开
    setTimeout(() => {
      initPPTPreview();
    }, 300);
  }
});

watch(visible, (val: boolean) => {
  emit('update:modelValue', val);
  if (!val) {
    // 清理预览内容
    if (pptPreviewRef.value) {
      pptPreviewRef.value.innerHTML = '';
    }
    error.value = '';
    pptxPreviewer = null;
  }
});

function handleClose() {
  visible.value = false;
}

function handleMaskClick() {
  // 点击遮罩层关闭弹框
  handleClose();
}

async function initPPTPreview() {
  if (!props.pptUrl) {
    error.value = '没有可预览的PPT文件';
    return;
  }

  loading.value = true;
  error.value = '';

  try {
    // 等待 DOM 更新
    await nextTick();
    await nextTick();

    // 添加重试机制，等待容器元素渲染
    let retryCount = 0;
    const maxRetries = 10;

    while (!pptPreviewRef.value && retryCount < maxRetries) {
      await new Promise(resolve => setTimeout(resolve, 100));
      retryCount++;
    }

    if (!pptPreviewRef.value) {
      console.log('调试信息:', {
        retryCount,
        maxRetries,
        pptPreviewRef: pptPreviewRef.value,
        visible: visible.value,
        loading: loading.value,
        error: error.value,
      });
      throw new Error('预览容器未找到');
    }

    // 清空容器内容
    pptPreviewRef.value.innerHTML = '';

    // 初始化pptx-preview预览器
    pptxPreviewer = init(pptPreviewRef.value, {
      width,
      height,
    });

    // 直接加载PPT文件
    if (props.pptUrl && pptxPreviewer) {
      await loadPPTFile();
    }
  }
  catch (err) {
    console.error('PPT预览初始化失败:', err);
    error.value = 'PPT预览初始化失败，请稍后重试';
    loading.value = false;
  }
}

async function loadPPTFile() {
  if (!props.pptUrl || !pptxPreviewer) {
    loading.value = false;
    return;
  }

  try {
    // 获取文件的ArrayBuffer格式数据
    const response = await fetch(props.pptUrl, {
      method: 'GET',
      headers: {
        Accept: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      },
    });

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const arrayBuffer = await response.arrayBuffer();

    if (arrayBuffer.byteLength === 0) {
      throw new Error('文件内容为空');
    }

    // 调用预览器的preview方法
    await pptxPreviewer.preview(arrayBuffer);

    loading.value = false;
  }
  catch (err) {
    console.error('PPT文件加载失败:', err);
    error.value = `PPT文件加载失败: ${err instanceof Error ? err.message : '未知错误'}`;
    loading.value = false;
  }
}

function retryLoad() {
  initPPTPreview();
}

function handleDownload() {
  if (props.downloadUrl) {
    const link = document.createElement('a');
    link.href = props.downloadUrl;
    link.download = 'presentation.pptx';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    ElMessage.success('开始下载PPT');
  }
}
</script>

<template>
  <!-- 自定义无边框弹框 -->
  <teleport to="body">
    <div v-if="visible" class="ppt-preview-modal" @click="handleMaskClick">
      <div class="modal-content" @click.stop>
        <!-- 右上角关闭按钮 -->
        <div class="close-btn" @click="handleClose">
          <el-icon>
            <Close />
          </el-icon>
        </div>

        <!-- 加载状态覆盖层 -->
        <div v-if="loading" class="loading-overlay">
          <div class="loading-container">
            <el-icon class="loading-icon">
              <Loading />
            </el-icon>
            <p>正在加载PPT预览...</p>
          </div>
        </div>

        <!-- 错误状态覆盖层 -->
        <div v-if="error" class="error-overlay">
          <div class="error-container">
            <el-icon class="error-icon">
              <Warning />
            </el-icon>
            <p>{{ error }}</p>
            <el-button type="primary" @click="retryLoad">
              重试
            </el-button>
          </div>
        </div>

        <!-- PPT预览容器 -->
        <div ref="pptPreviewRef" class="ppt-preview" />

        <!-- 悬浮下载按钮 -->
        <div v-if="downloadUrl && !loading && !error" class="download-btn" @click="handleDownload">
          <el-icon>
            <Download />
          </el-icon>
          <span>下载PPT</span>
        </div>
      </div>
    </div>
  </teleport>
</template>

<style scoped lang="scss">
// 自定义弹框遮罩层
.ppt-preview-modal {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgb(0 0 0 / 80%);
  backdrop-filter: blur(4px);
  animation: fadeIn 0.3s ease-out;
}

// 弹框内容容器
.modal-content {
  position: relative;
  width: 940px;
  height: 540px;
  padding: 12px;
  overflow: hidden;
  background-color: #ffffff;
  border-radius: 16px;
  box-shadow: 0 20px 60px rgb(0 0 0 / 30%);
  animation: slideIn 0.3s ease-out;
  .ppt-preview {
    width: 100%;
    height: 100%;
    max-height: 550px;
    overflow: auto;
  }
  &:deep(.pptx-preview-wrapper) {
    width: fit-content!important;
    height: fit-content!important;
    overflow: hidden;
  }

  // 右上角关闭按钮
  .close-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 30;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    color: white;
    cursor: pointer;
    background-color: rgb(0 0 0 / 70%);
    border-radius: 50%;
    transition: all 0.3s ease;
    &:hover {
      background-color: rgb(0 0 0 / 90%);
      transform: scale(1.1);
    }
    .el-icon {
      font-size: 14px;
    }
  }

  // 悬浮下载按钮
  .download-btn {
    position: absolute;
    bottom: 30px;
    left: 50%;
    z-index: 30;
    display: flex;
    gap: 10px;
    align-items: center;
    padding: 8px 14px;
    color: white;
    cursor: pointer;
    background: linear-gradient(135deg, #409eff, #337ecc);
    border-radius: 30px;
    box-shadow: 0 6px 20px rgb(64 158 255 / 40%);
    transform: translateX(-50%);
    transition: all 0.3s ease;
    &:hover {
      background: linear-gradient(135deg, #337ecc, #2a5aa0);
      box-shadow: 0 8px 25px rgb(64 158 255 / 50%);
      transform: translateX(-50%) translateY(-3px);
    }
    .el-icon {
      font-size: 12px;
    }
    span {
      font-size: 12px;
      font-weight: 600;
    }
  }

  // 加载和错误状态覆盖层
  .loading-overlay,
  .error-overlay {
    position: absolute;
    inset: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: rgb(255 255 255 / 95%);
    backdrop-filter: blur(2px);
  }
  .loading-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
    align-items: center;
    color: #666666;
    .loading-icon {
      font-size: 56px;
      animation: rotate 2s linear infinite;
    }
    p {
      margin: 0;
      font-size: 16px;
    }
  }
  .error-container {
    display: flex;
    flex-direction: column;
    gap: 20px;
    align-items: center;
    color: #f56c6c;
    .error-icon {
      font-size: 56px;
    }
    p {
      margin: 0;
      font-size: 16px;
      text-align: center;
    }
  }
}

// 动画效果
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes slideIn {
  from {
    opacity: 0;
    transform: scale(0.9) translateY(20px);
  }
  to {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

// 响应式设计
@media (width <=768px) {
  .modal-content {
    width: 98vw;
    height: 95vh;
    border-radius: 12px;
    .close-btn {
      top: 15px;
      right: 15px;
      width: 36px;
      height: 36px;
      .el-icon {
        font-size: 16px;
      }
    }
    .download-btn {
      bottom: 20px;
      padding: 12px 20px;
      .el-icon {
        font-size: 16px;
      }
      span {
        font-size: 14px;
      }
    }
  }
}
</style>
